package com.hailiang.saas.auth.filter;

import com.hailiang.mp.commonsource.api.CommonResult;
import com.hailiang.saas.auth.common.Constant;
import com.hailiang.saas.auth.config.AuthenticationConfig;
import com.hailiang.saas.auth.emuns.VerificationTypeEnum;
import com.hailiang.saas.auth.service.CommonService;
import com.hailiang.saas.auth.strategy.AbstractLoginAuthFilterStrategy;
import com.hailiang.saas.auth.strategy.AuthFilterStrategy;
import com.hailiang.saas.auth.emuns.AuthChannelEnum;
import com.hailiang.saas.auth.emuns.AuthEndpointEnum;
import com.hailiang.saas.auth.vo.AuthProtocol;
import com.hailiang.saas.auth.vo.login.VerificationLoginProtocol;
import com.hailiang.saas.auth.vo.verfication.PasswordFindProtocol;
import com.hailiang.saas.auth.vo.verfication.VerificationCodeProtocol;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.Objects;

/**
 *  基于短信验证码: 1、验证码登陆 2、验证码找回密码、修改密码、修改手机号
 * @author : pangfuzhong
 * @description
 * @date : 2021/9/27 16:21
 */
public class VerificationAuthFilter extends AbstractLoginAuthFilterStrategy implements AuthFilterStrategy {
    private AuthenticationConfig authenticationConfig;
    private RedisTemplate redisTemplate;
    public VerificationAuthFilter(AuthenticationConfig authenticationConfig) {
        this.authenticationConfig = authenticationConfig;
        this.redisTemplate = authenticationConfig.getRedisTemplate();
    }

    @Override
    public AuthEndpointEnum getAuthEndpointEnum() {
        return AuthEndpointEnum.WEB_BROWSER;
    }

    @Override
    public AuthChannelEnum getAuthChannelEnum() {
        return AuthChannelEnum.VERIFICATION;
    }

    @Override
    public String filterUrl() {
        return this.authenticationConfig.getVerificationAuthUrl();
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        if(!StringUtils.equals(this.filterUrl(), request.getRequestURL().toString()) && !this.match(request, response)) {
            // url不匹配 且 请求头信息不匹配 则向下游继续调用
            filterChain.doFilter(request, response);
        }

        CommonResult commonResult = CommonService.createResult();
        try {
            AuthProtocol authProtocol = this.createVerificationTypeProtocol(request, commonResult);
            this.verificationHandler(authProtocol, commonResult);
        } catch (Exception e) {
            commonResult.setSuccess(Boolean.FALSE);
            commonResult.setErrorCode(Constant.VERIFICATION_AUTH_HANDLER_CODE);
            commonResult.setMsg(Constant.VERIFICATION_AUTH_HANDLER_MSG + "," + e.getMessage());
            CommonService.returnResponse(response, commonResult);
        }
    }

    /**
     * 验证处理
     * @param authProtocol
     * @param commonResult
     * */
    private void verificationHandler(AuthProtocol authProtocol, CommonResult commonResult) {
        // 验证码获取处理
        if(VerificationTypeEnum.GET.equals(authProtocol.getVerificationType())) {
            VerificationCodeProtocol verificationCodeProtocol = (VerificationCodeProtocol) authProtocol;

            // todo 调用第三方接口获取验证码
            this.getVerificationHandler(verificationCodeProtocol);
        }

        // 验证码登陆处理
        if(VerificationTypeEnum.LOGIN.equals(authProtocol.getVerificationType())) {

        }

        // 验证码找回密码处理
        if(VerificationTypeEnum.FIND_PWD.equals(authProtocol.getVerificationType())) {

        }
    }

    /**
     * 获取验证码: 调用第三方接口获取当前账号(手机)验证码
     * @param verificationCodeProtocol
     * */
    private void getVerificationHandler(VerificationCodeProtocol verificationCodeProtocol) {
        try {
            String verificationCode = "A123456";


            // 将验证码存入redis, 方便后续验证
            String storeVerificationCodeKey = MessageFormat.format("{}_{}", Constant.VERIFICATION_CODE_KEY, verificationCodeProtocol.getAccountName());
        } catch (Exception e) {
            // 获取超时等
        }
    }

    /**
     * 获取关于含有验证码操作信息
     * @param request
     * @Param commonResult
     * @return
     * */
    private AuthProtocol createVerificationTypeProtocol(HttpServletRequest request, CommonResult commonResult) {
        String endPoint = request.getHeader(Constant.ENDPOINT_HEADER);
        String channel = request.getHeader(Constant.CHANNEL_HEADER);
        String type = request.getHeader(Constant.VERIFICATION_TYPE_HEADER);

        VerificationTypeEnum verificationTypeEnum = VerificationTypeEnum.getByCode(type);
        if(Objects.isNull(verificationTypeEnum)) {
            throw new RuntimeException(Constant.VERIFICATION_TYPE_WRONGFUL_MSG);
        }

        // 获取验证码
        if(VerificationTypeEnum.GET.equals(verificationTypeEnum)) {
            String accountName = request.getParameter(Constant.USERNAME);
            VerificationCodeProtocol verificationCodeProtocol = new VerificationCodeProtocol();
            verificationCodeProtocol.setEndPoint(endPoint);
            verificationCodeProtocol.setChannel(channel);
            verificationCodeProtocol.setAccountName(accountName);
            return verificationCodeProtocol;
        }

        // 验证码登陆
        if(VerificationTypeEnum.LOGIN.equals(verificationTypeEnum)) {
            String accountName = request.getParameter(Constant.USERNAME);
            VerificationLoginProtocol verificationLoginProtocol = new VerificationLoginProtocol();
            verificationLoginProtocol.setEndPoint(endPoint);
            verificationLoginProtocol.setChannel(channel);
            verificationLoginProtocol.setAccountName(accountName);
            verificationLoginProtocol.setVerificationCode(Constant.VERIFICATION_CODE);
            return verificationLoginProtocol;
        }

        // 验证码找回密码
        if(VerificationTypeEnum.FIND_PWD.equals(verificationTypeEnum)) {
            String accountName = request.getParameter(Constant.USERNAME);
            String verificationCode = request.getParameter(Constant.VERIFICATION_CODE);
            String oldPassword = request.getParameter(Constant.OLD_PASSWORD);
            String newPassword = request.getParameter(Constant.NEW_PASSWORD);
            PasswordFindProtocol passwordFindProtocol = new PasswordFindProtocol();
            passwordFindProtocol.setEndPoint(endPoint);
            passwordFindProtocol.setChannel(channel);
            passwordFindProtocol.setAccountName(accountName);
            passwordFindProtocol.setVerificationCode(Constant.VERIFICATION_CODE);
            passwordFindProtocol.setVerificationCode(verificationCode);
            passwordFindProtocol.setPassword(oldPassword);
            passwordFindProtocol.setPasswordAgain(newPassword);
            return passwordFindProtocol;
        }

        return null;
    }
}
